Atraskite sklandžias, programėles primenančias naršymo patirtis. Šis gidas tyrinėja CSS perėjimų pseudo-elementus, skirtus dinamiškiems puslapių perėjimams, pateikiant praktinius pavyzdžius.
CSS perėjimų tarp rodinių įvaldymas: išsami pseudo-elementų stiliaus analizė
Nuolat besikeičiančiame web programavimo pasaulyje siekis sukurti vientisą, sklandžią ir įtraukiančią vartotojo patirtį yra nuolatinis. Daugelį metų programuotojai stengėsi panaikinti atotrūkį tarp žiniatinklio ir natūraliųjų programėlių, ypač kalbant apie puslapių perėjimų sklandumą. Tradicinė žiniatinklio navigacija dažnai sukelia šiurkštų, viso puslapio perkrovimą – tuščią baltą ekraną, kuris akimirkai nutraukia vartotojo įsitraukimą. Vieno puslapio aplikacijos (SPA) šią problemą sušvelnino, tačiau individualių, prasmingų perėjimų kūrimas išliko sudėtinga ir dažnai trapi užduotis, labai priklausoma nuo JavaScript bibliotekų ir sudėtingo būsenos valdymo.
Pristatome CSS perėjimų tarp rodinių API (CSS View Transitions API) – technologiją, keičiančią žaidimo taisykles, kuri pakeis mūsų požiūrį į vartotojo sąsajos pakeitimus žiniatinklyje. Ši galinga API suteikia paprastą, tačiau neįtikėtinai lankstų mechanizmą animuoti perėjimus tarp skirtingų DOM būsenų, todėl dabar lengviau nei bet kada anksčiau sukurti išbaigtas, programėles primenančias patirtis, kurių tikisi vartotojai. Šios API galios pagrindas – naujų CSS pseudo-elementų rinkinys. Tai nėra tipiniai selektoriai; tai dinamiški, laikini elementai, kuriuos generuoja naršyklė, kad suteiktų jums detalią kiekvieno perėjimo etapo kontrolę. Šis gidas nuodugniai išnagrinės šį pseudo-elementų medį, tyrinėdamas, kaip stilizuoti kiekvieną komponentą, kad sukurtumėte įspūdingas, našias ir prieinamas animacijas pasaulinei auditorijai.
Perėjimo tarp rodinių anatomija
Prieš pradedant stilizuoti perėjimą, turime suprasti, kas vyksta „po gaubtu“, kai jis suaktyvinamas. Kai inicijuojate perėjimą tarp rodinių (pavyzdžiui, iškvietus document.startViewTransition()), naršyklė atlieka keletą veiksmų:
- Užfiksuoti seną būseną: Naršyklė padaro dabartinio puslapio būsenos „ekrano kopiją“.
- Atnaujinti DOM: Jūsų kodas atlieka pakeitimus DOM (pvz., pereina į naują rodinį, prideda ar pašalina elementus).
- Užfiksuoti naują būseną: Kai DOM atnaujinimas baigtas, naršyklė padaro naujos būsenos ekrano kopiją.
- Sukurti pseudo-elementų medį: Tuomet naršyklė sukonstruoja laikiną pseudo-elementų medį puslapio perdangoje. Šiame medyje yra užfiksuoti senos ir naujos būsenos vaizdai.
- Animuoti: Šiems pseudo-elementams pritaikomos CSS animacijos, sukuriant sklandų perėjimą iš senos būsenos į naują. Numatytasis efektas yra paprastas kryžminis išnykimas (cross-fade).
- Išvalyti: Kai animacijos baigiamos, pseudo-elementų medis pašalinamas, ir vartotojas gali sąveikauti su nauju, gyvu DOM.
Pritaikymo raktas yra šis laikinas pseudo-elementų medis. Įsivaizduokite jį kaip sluoksnių rinkinį dizaino įrankyje, laikinai uždėtą ant jūsų puslapio. Jūs turite visišką CSS kontrolę virš šių sluoksnių. Štai struktūra, su kuria dirbsite:
- ::view-transition
- ::view-transition-group(*)
- ::view-transition-image-pair(*)
- ::view-transition-old(*)
- ::view-transition-new(*)
- ::view-transition-image-pair(*)
- ::view-transition-group(*)
Paanalizuokime, ką reiškia kiekvienas iš šių pseudo-elementų.
Pseudo-elementų sudėtis
::view-transition: Tai visos struktūros šaknis. Tai vienas elementas, kuris užpildo peržiūros sritį ir yra virš viso kito puslapio turinio. Jis veikia kaip konteineris visoms pereinančioms grupėms ir yra puiki vieta nustatyti bendras perėjimo savybes, tokias kaip trukmė ar laiko funkcija.
::view-transition-group(*): Kiekvienam atskiram pereinančiam elementui (identifikuojamam pagal view-transition-name CSS savybę) sukuriama grupė. Šis pseudo-elementas yra atsakingas už savo turinio pozicijos ir dydžio animavimą. Jei turite kortelę, kuri juda iš vienos ekrano pusės į kitą, tai būtent ::view-transition-group ir juda.
::view-transition-image-pair(*): Įdėtas grupės viduje, šis elementas veikia kaip konteineris ir karpymo kaukė senam ir naujam rodiniui. Jo pagrindinis vaidmuo yra išlaikyti efektus, tokius kaip border-radius ar transform, animacijos metu ir valdyti numatytąją kryžminio išnykimo animaciją.
::view-transition-old(*): Tai atspindi elemento „ekrano kopiją“ arba atvaizduotą rodinį jo senoje būsenoje (prieš DOM pasikeitimą). Pagal numatytuosius nustatymus, jis animuojamas nuo opacity: 1 iki opacity: 0.
::view-transition-new(*): Tai atspindi elemento „ekrano kopiją“ arba atvaizduotą rodinį jo naujoje būsenoje (po DOM pasikeitimo). Pagal numatytuosius nustatymus, jis animuojamas nuo opacity: 0 iki opacity: 1.
Šaknis: ::view-transition pseudo-elemento stilizavimas
::view-transition pseudo-elementas yra drobė, ant kurios tapoma visa jūsų animacija. Kaip aukščiausio lygio konteineris, tai ideali vieta apibrėžti savybes, kurios turėtų būti taikomos globaliai visam perėjimui. Pagal numatytuosius nustatymus naršyklė pateikia animacijų rinkinį, tačiau jūs galite jas lengvai perrašyti.
Pavyzdžiui, numatytasis perėjimas yra kryžminis išnykimas, trunkantis 250 milisekundžių. Jei norite tai pakeisti kiekvienam perėjimui savo svetainėje, galite nusitaikyti į šakninį pseudo-elementą:
::view-transition {
animation-duration: 500ms;
animation-timing-function: ease-in-out;
}
Ši paprasta taisyklė dabar priverčia visus numatytuosius puslapio išnykimus trukti dvigubai ilgiau ir naudoti „ease-in-out“ kreivę, suteikdama jiems šiek tiek kitokį pojūtį. Nors čia galite taikyti sudėtingas animacijas, paprastai geriausia šią vietą naudoti universaliems laiko ir lėtėjimo nustatymams apibrėžti, leidžiant specifiškesniems pseudo-elementams tvarkyti detalią choreografiją.
Grupavimas ir pavadinimai: `view-transition-name` galia
Be papildomų nustatymų, „View Transition API“ suteikia viso puslapio kryžminį išnykimą. Tai valdo viena pseudo-elementų grupė, skirta šakniniam elementui. Tikroji API galia atsiskleidžia, kai norite animuoti perėjimą tarp specifinių, atskirų elementų būsenų. Pavyzdžiui, kai produkto miniatiūra sąrašo puslapyje sklandžiai išauga ir persikelia į pagrindinio produkto paveikslėlio poziciją detalės puslapyje.
Norėdami pranešti naršyklei, kad du elementai skirtingose DOM būsenose yra konceptualiai tas pats, naudojate view-transition-name CSS savybę. Ši savybė turi būti pritaikyta tiek pradiniam, tiek galutiniam elementui.
/* Sąrašo puslapio CSS */
.product-thumbnail {
view-transition-name: product-image;
}
/* Detalės puslapio CSS */
.main-product-image {
view-transition-name: product-image;
}
Suteikdami abiem elementams tą patį unikalų pavadinimą (šiuo atveju „product-image“), jūs nurodote naršyklei: „Užuot tiesiog išnykdžius seną puslapį ir atsiradus naujam, sukurk specialų perėjimą šiam konkrečiam elementui.“ Dabar naršyklė sukurs specialią ::view-transition-group(product-image), kad valdytų jo animaciją atskirai nuo šakninio išnykimo. Tai yra pagrindinis konceptas, leidžiantis sukurti populiarų „persikeitimo“ (morphing) arba „bendro elemento“ perėjimo efektą.
Svarbi pastaba: Bet kuriuo perėjimo momentu view-transition-name turi būti unikalus. Negalite turėti dviejų matomų elementų su tuo pačiu pavadinimu vienu metu.
Išsamus stilizavimas: pagrindiniai pseudo-elementai
Pavadintiems elementams dabar galime pasinerti į specifinių pseudo-elementų, kuriuos naršyklė jiems sugeneruoja, stilizavimą. Čia galite sukurti išties individualias ir išraiškingas animacijas.
`::view-transition-group(name)`: Judintojas
Grupės vienintelė atsakomybė yra pereiti nuo senojo elemento dydžio ir pozicijos prie naujojo elemento dydžio ir pozicijos. Ji neapima tikrojo turinio išvaizdos, tik jo ribų laukelį (bounding box). Galvokite apie tai kaip apie judantį rėmelį.
Pagal numatytuosius nustatymus, naršyklė animuoja jo transform ir width/height savybes. Galite tai perrašyti, kad sukurtumėte skirtingus efektus. Pavyzdžiui, galėtumėte pridėti judėjimui lanką, animuodami jį lenkta trajektorija, arba priversti jį didėti ir mažėti kelionės metu.
::view-transition-group(product-image) {
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
Šiame pavyzdyje mes taikome specifinę lėtėjimo funkciją tik produkto paveikslėlio judėjimui, suteikdami jam dinamiškesnį ir fizikinį pojūtį, nepaveikiant numatytojo likusio puslapio išnykimo.
`::view-transition-image-pair(name)`: Kirpėjas ir išnykdintojas
Įdėta judančios grupės viduje, vaizdų pora laiko senąjį ir naująjį rodinius. Ji veikia kaip karpymo kaukė, todėl jei jūsų elementas turi border-radius, vaizdų pora užtikrina, kad turinys išliktų apkirptas su tuo spinduliu visos dydžio ir pozicijos animacijos metu. Kitas jos pagrindinis darbas yra organizuoti numatytąjį kryžminį išnykimą tarp senojo ir naujojo turinio.
Galbūt norėsite stilizuoti šį elementą, siekdami vizualinio nuoseklumo ar kurdami pažangesnius efektus. Svarbi savybė, kurią reikia apsvarstyti, yra isolation: isolate. Tai yra labai svarbu, jei planuojate naudoti pažangius mix-blend-mode efektus vaikiniams elementams (senam ir naujam), nes tai sukuria naują išdėstymo kontekstą ir neleidžia maišymui paveikti elementų, esančių už perėjimo grupės ribų.
::view-transition-image-pair(product-image) {
isolation: isolate;
}
`::view-transition-old(name)` ir `::view-transition-new(name)`: Scenos žvaigždės
Tai pseudo-elementai, kurie atspindi jūsų elemento vizualinę išvaizdą prieš ir po DOM pakeitimo. Čia vyks didžioji dalis jūsų individualios animacijos darbo. Pagal numatytuosius nustatymus, naršyklė paleidžia paprastą kryžminio išnykimo animaciją, naudodama opacity ir mix-blend-mode. Norėdami sukurti individualią animaciją, pirmiausia turite išjungti numatytąją.
::view-transition-old(name),
::view-transition-new(name) {
animation: none;
}
Kai numatytoji animacija yra išjungta, galite laisvai taikyti savo. Panagrinėkime keletą įprastų modelių.
Individuali animacija: slinkimas
Vietoj kryžminio išnykimo, padarykime, kad konteinerio turinys įslinktų. Pavyzdžiui, naršant tarp straipsnių, norime, kad naujo straipsnio tekstas įslinktų iš dešinės, o senas tekstas išslinktų į kairę.
Pirma, apibrėžkime kadrus (keyframes):
@keyframes slide-from-right {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
@keyframes slide-to-left {
from { transform: translateX(0); }
to { transform: translateX(-100%); }
}
Dabar pritaikykime šias animacijas senam ir naujam pseudo-elementams, skirtiems pavadintam elementui „article-content“.
::view-transition-old(article-content) {
animation: 300ms ease-out forwards slide-to-left;
}
::view-transition-new(article-content) {
animation: 300ms ease-out forwards slide-from-right;
}
Individuali animacija: 3D apvertimas
Dramatiškesniam efektui galite sukurti 3D kortelės apvertimą. Tam reikia animuoti transform savybę su rotateY ir taip pat valdyti backface-visibility.
/* Grupei reikalingas 3D kontekstas */
::view-transition-group(card-flipper) {
transform-style: preserve-3d;
}
/* Vaizdų pora taip pat turi išsaugoti 3D kontekstą */
::view-transition-image-pair(card-flipper) {
transform-style: preserve-3d;
}
/* Senas rodinys apsiverčia nuo 0 iki -180 laipsnių */
::view-transition-old(card-flipper) {
animation: 600ms ease-in forwards flip-out;
backface-visibility: hidden;
}
/* Naujas rodinys apsiverčia nuo 180 iki 0 laipsnių */
::view-transition-new(card-flipper) {
animation: 600ms ease-out forwards flip-in;
backface-visibility: hidden;
}
@keyframes flip-out {
from { transform: rotateY(0deg); }
to { transform: rotateY(-180deg); }
}
@keyframes flip-in {
from { transform: rotateY(180deg); }
to { transform: rotateY(0deg); }
}
Praktiniai pavyzdžiai ir pažangios technikos
Teorija yra naudinga, bet praktinis pritaikymas yra tai, kur mes tikrai mokomės. Panagrinėkime keletą įprastų scenarijų ir kaip juos išspręsti naudojant perėjimų tarp rodinių pseudo-elementus.
Pavyzdys: „persikeičianti“ kortelės miniatiūra
Tai klasikinis bendro elemento perėjimas. Įsivaizduokite vartotojų profilių galeriją. Kiekvienas profilis yra kortelė su avataru. Kai spustelite kortelę, pereinate į detalų puslapį, kuriame tas pats avataras yra ryškiai rodomas viršuje.
1 žingsnis: priskirkite pavadinimus
Galerijos puslapyje avataro paveikslėlis gauna pavadinimą. Pavadinimas turėtų būti unikalus kiekvienai kortelei, pavyzdžiui, pagrįstas vartotojo ID.
/* gallery-item.css faile */
.card-avatar { view-transition-name: avatar-user-123; }
Profilio detalės puslapyje didelis antraštės avataras gauna lygiai tą patį pavadinimą.
/* profile-page.css faile */
.profile-header-avatar { view-transition-name: avatar-user-123; }
2 žingsnis: pritaikykite animaciją
Pagal numatytuosius nustatymus naršyklė perkels ir pakeis avataro mastelį, bet taip pat atliks kryžminį turinio išnykimą. Jei vaizdas yra identiškas, šis išnykimas yra nereikalingas ir gali sukelti nežymų mirgėjimą. Mes galime jį išjungti.
/* Žvaigždutė (*) čia yra pakaitos simbolis, reiškiantis bet kurią pavadintą grupę */
::view-transition-image-pair(*) {
/* Išjungiame numatytąjį išnykimą */
animation-duration: 0s;
}
Palaukite, jei išjungsime išnykimą, kaip pasikeis turinys? Bendriems elementams, kurių senas ir naujas rodiniai yra identiški, naršyklė yra pakankamai protinga, kad visam perėjimui naudotų tik vieną rodinį. `image-pair` iš esmės laiko tik vieną vaizdą, todėl išjungus išnykimą tiesiog atskleidžiama ši optimizacija. Elementams, kurių turinys iš tikrųjų keičiasi, jums reikėtų individualios animacijos vietoj numatytojo išnykimo.
Kraštinių santykio pokyčių valdymas
Dažnas iššūkis kyla, kai pereinantis elementas pakeičia savo kraštinių santykį. Pavyzdžiui, 16:9 horizontali miniatiūra sąrašo puslapyje gali pereiti į 1:1 kvadratinį avatarą detalės puslapyje. Numatytasis naršyklės elgesys yra animuoti plotį ir aukštį nepriklausomai, dėl ko vaizdas perėjimo metu atrodo suspaustas arba ištampytas.
Sprendimas yra elegantiškas. Mes leidžiame ::view-transition-group valdyti dydžio ir pozicijos pasikeitimą, bet perrašome senų ir naujų vaizdų stilių jo viduje.
Tikslas yra priversti seną ir naują „ekrano kopijas“ užpildyti savo konteinerį neiškraipant. Tai galime padaryti nustatydami jų plotį ir aukštį į 100% ir leisdami naršyklės numatytajai object-fit savybei (kuri paveldima iš pradinio elemento) teisingai valdyti mastelį.
::view-transition-old(hero-image),
::view-transition-new(hero-image) {
/* Išvengiame iškraipymo užpildydami konteinerį */
width: 100%;
height: 100%;
/* Perrašome numatytąjį kryžminį išnykimą, kad aiškiai matytume efektą */
animation: none;
}
Su šiuo CSS, `image-pair` sklandžiai animuos savo kraštinių santykį, o viduje esantys vaizdai bus teisingai apkirpti arba su juodomis juostomis (priklausomai nuo jų `object-fit` vertės), lygiai taip, kaip jie būtų įprastame konteineryje. Tada galite pridėti savo individualias animacijas, pavyzdžiui, kryžminį išnykimą, ant šios pataisytos geometrijos.
Derinimas ir naršyklių palaikymas
Stilizuoti elementus, kurie egzistuoja tik sekundės dalį, gali būti sudėtinga. Laimei, šiuolaikinės naršyklės tam siūlo puikius programuotojo įrankius. „Chrome“ ar „Edge DevTools“ galite eiti į „Animations“ (Animacijos) skydelį, ir kai suaktyvinate perėjimą tarp rodinių, galite jį sustabdyti. Sustabdę animaciją, galite naudoti „Elements“ (Elementai) skydelį, kad patikrintumėte visą `::view-transition` pseudo-elementų medį, kaip ir bet kurią kitą DOM dalį. Galite matyti taikomus stilius ir netgi juos modifikuoti realiu laiku, kad ištobulintumėte savo animacijas.
Nuo 2023 m. pabaigos „View Transitions API“ palaiko „Chromium“ pagrindu veikiančios naršyklės („Chrome“, „Edge“, „Opera“). Implementacijos vykdomos „Firefox“ ir „Safari“. Tai daro šią technologiją puikia kandidate progresyviam tobulinimui. Vartotojai su palaikančiomis naršyklėmis gauna malonią, patobulintą patirtį, o vartotojai su kitomis naršyklėmis gauna standartinę, momentinę navigaciją. Galite patikrinti palaikymą CSS:
@supports (view-transition: none) {
/* Visi perėjimų tarp rodinių stiliai eina čia */
::view-transition-old(my-element) { ... }
}
Geriausios praktikos pasaulinei auditorijai
Įgyvendinant animacijas, būtina atsižvelgti į įvairius vartotojus ir įrenginius visame pasaulyje.
Našumas: Animacijos turi būti greitos ir sklandžios. Stenkitės animuoti CSS savybes, kurias naršyklei apdoroti yra pigu, pirmiausia transform ir opacity. Animuojant savybes, tokias kaip width, height ar margin, kiekviename kadre gali būti iš naujo skaičiuojamas išdėstymas, o tai sukelia strigimą ir prastą patirtį, ypač mažesnės galios įrenginiuose.
Prieinamumas: Kai kurie vartotojai patiria judesio ligą ar diskomfortą dėl animacijų. Visos pagrindinės operacinės sistemos suteikia vartotojo nuostatą sumažinti judesį. Turime tai gerbti. prefers-reduced-motion medijos užklausa leidžia išjungti arba supaprastinti animacijas šiems vartotojams.
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
/* Praleidžiame visas individualias animacijas ir naudojame greitą, paprastą išnykimą */
animation: none !important;
}
}
Vartotojo patirtis (UX): Geri perėjimai yra tikslingi. Jie turėtų nukreipti vartotojo dėmesį ir suteikti kontekstą apie vartotojo sąsajoje vykstantį pasikeitimą. Per lėta animacija gali priversti aplikaciją atrodyti vangi, o per daug ryški – blaškyti. Siekite, kad perėjimo trukmė būtų nuo 200 ms iki 500 ms. Tikslas – kad animacija būtų labiau jaučiama, nei matoma.
Išvada: ateitis yra sklandi
CSS perėjimų tarp rodinių API, o ypač jos galingas pseudo-elementų medis, reiškia milžinišką šuolį į priekį žiniatinklio vartotojo sąsajoms. Ji suteikia programuotojams natūralų, našų ir labai pritaikomą įrankių rinkinį, skirtą kurti tokius sklandžius, būseną išlaikančius perėjimus, kurie kadaise buvo išskirtinai natūraliųjų programėlių sritis. Suprasdami ::view-transition, ::view-transition-group ir senų/naujų vaizdų porų vaidmenis, galite pereiti nuo paprastų išnykimų ir kurti sudėtingas, prasmingas animacijas, kurios pagerina naudojimąsi ir džiugina vartotojus.
Plečiantis naršyklių palaikymui, ši API taps būtina šiuolaikinio front-end programuotojo įrankių rinkinio dalimi. Pasinaudodami jos galimybėmis ir laikydamiesi geriausių našumo bei prieinamumo praktikų, galime kurti žiniatinklį, kuris yra ne tik funkcionalesnis, bet ir gražesnis bei intuityvesnis visiems ir visur.